#pragma once
#ifndef ___MOD_binary_HPP
#define ___MOD_binary_HPP
#include "../config.hpp"
#include <string>
#include <vector>
#include <algorithm>
#include <io.h>
#include <fstream>
#include <sstream>
__MOD_BEGIN
class binary :public std::vector<unsigned char>
{
private:
	using _Ty = unsigned char;
	using _Alloc = std::allocator<_Ty>;
	using size_type = typename _Alty_traits::size_type;
	using _Mybase = std::vector<_Ty>;
public:
	static constexpr auto npos{ static_cast<size_type>(-1) };
	__forceinline operator char* () { return (char*)this->data(); }
	__forceinline operator const char* () { return (const char*)this->data(); }
	__forceinline operator binary& () { return *this; }
public:
	__forceinline std::string to_string(){ return std::string((const char*)this->data(), this->size()); }
public:
	__forceinline binary() noexcept : _Mybase() {}
	__forceinline explicit binary(const _Alloc& _Al) noexcept : _Mybase(_Al) {}
	__forceinline explicit binary(const size_type _Count, const _Alloc& _Al = _Alloc()) : _Mybase(_Count, _Al) {}
	__forceinline binary(const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) : _Mybase(_Count, _Val, _Al) {}
	__forceinline binary(size_type _Count, const bool& _Val, const _Alloc& _Al = _Alloc()) : _Mybase(_Count, _Val, _Al) {}
public:
	__forceinline binary(const binary _Right, const size_type _Count, const _Alloc& _Al = _Alloc()) : _Mybase(_Right._Unchecked_begin(), _Right._Unchecked_begin() + _Count, _Al) {}
	__forceinline binary(binary&& _Right) noexcept : _Mybase(_Right) {}
	__forceinline binary(binary&& _Right, const _Alloc& _Al) noexcept : _Mybase(_Right, _Al) {}
	__forceinline binary(std::vector<_Ty>& _Right) : _Mybase(_Right) {}
	__forceinline binary(const binary& _Right) : _Mybase(_Right) {}
	__forceinline binary(const binary& _Right, const _Alloc& _Al) : _Mybase(_Right, _Al) {}
	__forceinline binary(const std::vector<_Ty>& _Right) : _Mybase(_Right) {}
	__forceinline binary(std::initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) : _Mybase(_Ilist, _Al) {}
	template <class _Iter, std::enable_if_t<std::_Is_iterator_v<_Iter>, int> = 0>
	__forceinline binary(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_First, _Last, _Al) {}
	__forceinline binary(_Ty* _First, _Ty* _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_First, _Last, _Al) {}
public:
	__forceinline binary& operator=(binary& _Right) noexcept { _Mybase::operator=(_Right); return *this; }
	__forceinline binary& operator=(binary&& _Right) noexcept { _Mybase::operator=(_Right); return *this; }
	__forceinline binary& operator=(std::vector<_Ty>& _Right) { _Mybase::operator=(_Right); return *this; }
	__forceinline binary& operator=(std::initializer_list<_Ty> _Ilist) { _Mybase::operator=(_Ilist); return *this; }
	__forceinline binary& operator=(const binary& _Right) { _Mybase::operator=(_Right); return *this; }
	__forceinline binary& operator=(const binary&& _Right) noexcept { _Mybase::operator=(_Right); return *this; }
	__forceinline binary& operator=(const std::vector<_Ty>& _Right) { _Mybase::operator=(_Right); return *this; }
public:
	template <class _Elem = char>
	bool loadfile(const _Elem* const _Filename, std::ios_base::openmode _Mode = std::ios_base::in | std::ios::binary, int _Prot = std::ios_base::_Default_open_prot)
	{
		std::basic_ifstream<_Elem, std::char_traits<_Elem>> hFile;
		hFile.open(_Filename, _Mode, _Prot);
		if (!hFile.is_open())
		{
			this->clear();
			return false;
		}
		hFile.seekg(0, std::ios::end);
		std::streampos length = hFile.tellg();
		hFile.seekg(0, std::ios::beg);
		this->resize((size_t)length);
		bool is_ok = true;
		if (!hFile.read((char*)this->data(), length))
		{
			this->clear();
			is_ok = false;
		}
		hFile.close();
		return is_ok;
	}
	template <class _Elem = char>
	bool writefile(const _Elem* const _Filename, std::ios_base::openmode _Mode = std::ios_base::out | std::ios::binary, int _Prot = std::ios_base::_Default_open_prot)
	{
		std::basic_ofstream<_Elem, std::char_traits<_Elem>> hFile;
		hFile.open(_Filename, _Mode, _Prot);
		if (!hFile.is_open())
		{
			return false;
		}
		if (hFile.write((char*)this->data(), this->size()).fail())
		{
			hFile.close();
			return false;
		}
		hFile.close();
		return true;
	}
public:
	__forceinline bool equal(std::initializer_list<_Ty> _Right)
	{
		return this->size() == _Right.size() && std::equal(this->_Unchecked_begin(), this->_Unchecked_end(), _Right.begin());
	}
	__forceinline _Ty& operator[](const size_type _Pos) noexcept
	{
		return _Mybase::operator[](_Pos);
	}
	__forceinline const _Ty& operator[](const size_type _Pos) const noexcept
	{
		return _Mybase::operator[](_Pos);
	}
public:
	__forceinline binary& operator+(binary& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(std::initializer_list<_Ty> _Right) { __append(_Right.begin(), _Right.size()); return *this; }
	__forceinline binary& operator+(std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(std::string _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(std::wstring _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(const binary& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(const binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(const std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+(char _Right) { __append(&_Right, sizeof(char)); return *this; }
	__forceinline binary& operator+(_Ty _Right) { __append(&_Right, sizeof(_Ty)); return *this; }
	__forceinline binary& operator+(short _Right) { __append(&_Right, sizeof(short)); return *this; }
	__forceinline binary& operator+(unsigned short _Right) { __append(&_Right, sizeof(unsigned short)); return *this; }
	__forceinline binary& operator+(int _Right) { __append(&_Right, sizeof(int)); return *this; }
	__forceinline binary& operator+(unsigned int _Right) { __append(&_Right, sizeof(unsigned int)); return *this; }
	__forceinline binary& operator+(long _Right) { __append(&_Right, sizeof(long)); return *this; }
	__forceinline binary& operator+(unsigned long _Right) { __append(&_Right, sizeof(unsigned long)); return *this; }
	__forceinline binary& operator+(__int64 _Right) { __append(&_Right, sizeof(__int64)); return *this; }
	__forceinline binary& operator+(unsigned __int64 _Right) { __append(&_Right, sizeof(unsigned __int64)); return *this; }
	__forceinline binary& operator+(float _Right) { __append(&_Right, sizeof(float)); return *this; }
	__forceinline binary& operator+(double _Right) { __append(&_Right, sizeof(double)); return *this; }
public:
	__forceinline binary& operator<<(binary& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(std::initializer_list<_Ty> _Right) { __append(_Right.begin(), _Right.size()); return *this; }
	__forceinline binary& operator<<(std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(std::string _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(std::wstring _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(const binary& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(const binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(const std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator<<(char _Right) { __append(&_Right, sizeof(char)); return *this; }
	__forceinline binary& operator<<(_Ty _Right) { __append(&_Right, sizeof(_Ty)); return *this; }
	__forceinline binary& operator<<(short _Right) { __append(&_Right, sizeof(short)); return *this; }
	__forceinline binary& operator<<(unsigned short _Right) { __append(&_Right, sizeof(unsigned short)); return *this; }
	__forceinline binary& operator<<(int _Right) { __append(&_Right, sizeof(int)); return *this; }
	__forceinline binary& operator<<(unsigned int _Right) { __append(&_Right, sizeof(unsigned int)); return *this; }
	__forceinline binary& operator<<(long _Right) { __append(&_Right, sizeof(long)); return *this; }
	__forceinline binary& operator<<(unsigned long _Right) { __append(&_Right, sizeof(unsigned long)); return *this; }
	__forceinline binary& operator<<(__int64 _Right) { __append(&_Right, sizeof(__int64)); return *this; }
	__forceinline binary& operator<<(unsigned __int64 _Right) { __append(&_Right, sizeof(unsigned __int64)); return *this; }
	__forceinline binary& operator<<(float _Right) { __append(&_Right, sizeof(float)); return *this; }
	__forceinline binary& operator<<(double _Right) { __append(&_Right, sizeof(double)); return *this; }
public:
	__forceinline binary& operator+=(binary& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+=(binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+=(std::initializer_list<_Ty> _Right) { __append(_Right.begin(), _Right.size()); return *this; }
	__forceinline binary& operator+=(std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+=(std::string _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+=(std::wstring _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+=(const binary& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+=(const binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& operator+=(const std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
public:
	__forceinline binary& append(binary& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& append(binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& append(std::initializer_list<_Ty> _Right) { __append(_Right.begin(), _Right.size()); return *this; }
	__forceinline binary& append(std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& append(std::string _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& append(std::wstring _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& append(const binary& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& append(const binary&& _Right) noexcept { __append(_Right.data(), _Right.size()); return *this; }
	__forceinline binary& append(const std::vector<_Ty>& _Right) { __append(_Right.data(), _Right.size()); return *this; }
	template <class _Iter, std::enable_if_t<std::_Is_iterator_v<_Iter>, int> = 0>
	__forceinline binary& append(_Iter _First, _Iter _Last) { _Mybase::size() == 0 ? _Mybase::assign(_First, _Last) : _Mybase::insert(_Mybase::end(), _First, _Last); return *this; }
	__forceinline binary& append(_Ty* _First, _Ty* _Last) { __append(_First, _Last);  return *this; }
	__forceinline binary& append(void* _First, size_t len) { __append(_First, len);  return *this; }
	__forceinline binary& append(char _Right) { __append(&_Right, sizeof(char)); return *this; }
	__forceinline binary& append(_Ty _Right) { __append(&_Right, sizeof(_Ty)); return *this; }
	__forceinline binary& append(short _Right) { __append(&_Right, sizeof(short)); return *this; }
	__forceinline binary& append(unsigned short _Right) { __append(&_Right, sizeof(unsigned short)); return *this; }
	__forceinline binary& append(int _Right) { __append(&_Right, sizeof(int)); return *this; }
	__forceinline binary& append(unsigned int _Right) { __append(&_Right, sizeof(unsigned int)); return *this; }
	__forceinline binary& append(long _Right) { __append(&_Right, sizeof(long)); return *this; }
	__forceinline binary& append(unsigned long _Right) { __append(&_Right, sizeof(unsigned long)); return *this; }
	__forceinline binary& append(__int64 _Right) { __append(&_Right, sizeof(__int64)); return *this; }
	__forceinline binary& append(unsigned __int64 _Right) { __append(&_Right, sizeof(unsigned __int64)); return *this; }
	__forceinline binary& append(float _Right) { __append(&_Right, sizeof(float)); return *this; }
	__forceinline binary& append(double _Right) { __append(&_Right, sizeof(double)); return *this; }
public:
	template <class _Elem>
	__inline void assign_s(const _Elem* const _Val, _Alty_traits::size_type _Count)
	{
		_Mybase::assign((_Ty*)_Val, (_Ty*)(_Val + (_Count)));
	}
	__inline size_type find(const binary& _Right, const size_type _Off = 0) const noexcept
	{
		using _Traits = std::char_traits<_Ty>;
		return static_cast<size_type>(std::_Traits_find<_Traits>(_Mybase::_Unchecked_begin(), _Mybase::size(), _Off, _Right._Unchecked_begin(), _Right.size()));
	}
	__inline size_type rfind(const binary& _Right, const size_type _Off = binary::npos) const noexcept
	{
		using _Traits = std::char_traits<_Ty>;
		return static_cast<size_type>(std::_Traits_rfind<_Traits>(_Mybase::_Unchecked_begin(), _Mybase::size(), _Off, _Right._Unchecked_begin(), _Right.size()));
	}
	__inline size_type search(std::initializer_list<int> _Right, const size_type _Off = 0)
	{
		std::vector<unsigned char>::iterator _res = std::search(this->begin() + _Off, this->end(), _Right.begin(), _Right.end(), _search_callback);
		if (_res != this->end())
		{
			return (size_t)(_res - this->begin());
		}
		return binary::npos;
	}
	__inline binary mid(const size_type _Off, const size_type _Count = binary::npos) const
	{
		unsigned char* _begin = (unsigned char*)this->_Unchecked_begin() + _Off;
		unsigned char* _end = (unsigned char*)_begin + _Count;
		unsigned char* _c_end = (unsigned char*)this->_Unchecked_end();
		if (_begin >= _c_end)
		{
			return binary();
		}
		if (_end > _c_end)
		{
			_end = _c_end;
		}
		return binary(_begin, _end, get_allocator());
	}
	__inline binary left(size_t Cout)
	{
		size_t len = this->size();
		return Cout > len ? binary() : this->mid(0, Cout);
	}
	__inline binary right(size_t Cout)
	{
		size_t len = this->size();
		return Cout > len ? binary() : this->mid(len - Cout, Cout);
	}
	__inline bool first_with(const binary& _Right)
	{
		return this->size() >= _Right.size() && std::equal(_Right._Unchecked_begin(), _Right._Unchecked_end(), this->_Unchecked_begin());
	}
	__inline bool last_with(const binary& _Right)
	{
		return this->size() >= _Right.size() && std::equal(_Right.rbegin(), _Right.rend(), this->rbegin());
	}
	__inline bool contains(const binary& _Right)
	{
		std::vector<unsigned char>::iterator _end = this->end();
		return std::search(this->begin(), _end, _Right.begin(), _Right.end()) != _end;
	}
	__inline iterator erase(const size_type _Off, const size_type _Count)
	{
		std::vector<unsigned char>::iterator _begin = this->begin() + _Off;
		std::vector<unsigned char>::iterator _end = _begin + _Count;
		std::vector<unsigned char>::iterator _t_end = this->end();
		if (_begin >= _t_end)
		{
			return _t_end;
		}
		if (_end > _t_end)
		{
			_end = _t_end;
		}
		return _Mybase::erase(_begin, _end);
	}
	//this->erase();
private:
	__inline static bool _search_callback(unsigned char i, unsigned int j)
	{
		return i == j || j == 256;
	}
	template <class _Iter, std::enable_if_t<std::_Is_iterator_v<_Iter>, int> = 0>
	__forceinline void __append(_Iter _First, _Iter _Last)
	{
		if (_Mybase::size() == 0)
		{
			_Mybase::assign(_First, _Last);
		}
		else
		{
			_Mybase::insert(_Mybase::end(), _First, _Last);
		}
	}
	__forceinline void __append(_Ty* _First, _Ty* _Last)
	{
		if (_Mybase::size() == 0)
		{
			_Mybase::assign(_First, _Last);
		}
		else
		{
			_Mybase::insert(_Mybase::end(), (_Ty*)_First, (_Ty*)_Last);
		}
	}
	__forceinline void __append(const void* v, _Alty_traits::size_type len)
	{
		_Ty* _begin = (_Ty*)v;
		_Ty* _end = (_Ty*)v + len;
		__append(_begin, _end);
		return;
	}
};
__forceinline std::initializer_list<unsigned char> to_binary(std::initializer_list<unsigned char> _Ilist)
{
	return _Ilist;
}

__forceinline bool operator==(const binary& _Left, const binary& _Right)
{
	return _Left.size() == _Right.size() && std::equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end());
}
__forceinline bool operator!=(const binary& _Left, const binary& _Right)
{
	return !(_Left == _Right);
}
__forceinline bool operator<(const binary& _Left, const binary& _Right)
{
	return std::lexicographical_compare(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end());
}
__forceinline bool operator>(const binary& _Left, const binary& _Right)
{
	return _Right < _Left;
}
__forceinline bool operator<=(const binary& _Left, const binary& _Right)
{
	return !(_Right < _Left);
}
__forceinline bool operator>=(const binary& _Left, const binary& _Right)
{
	return !(_Left < _Right);
}
__forceinline bool operator==(const binary& _Left, const std::initializer_list<unsigned char>& _Right)
{
	return _Left.size() == _Right.size() && std::equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right.begin(), _Right.end());
}
__forceinline bool operator!=(const binary& _Left, const std::initializer_list<unsigned char>& _Right)
{
	return !(_Left == _Right);
}
__forceinline bool operator<(const binary& _Left, const std::initializer_list<unsigned char>& _Right)
{
	return std::lexicographical_compare(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right.begin(), _Right.end());
}
__forceinline bool operator>(const binary& _Left, const std::initializer_list<unsigned char>& _Right)
{
	return _Right < _Left;
}
__forceinline bool operator<=(const binary& _Left, const std::initializer_list<unsigned char>& _Right)
{
	return !(_Right < _Left);
}
__forceinline bool operator>=(const binary& _Left, const std::initializer_list<unsigned char>& _Right)
{
	return !(_Left < _Right);
}
__MOD_END
#endif